﻿/**
 * nPnP - neither Perl not PHP
 *
 * Copyright (C) 2009 Christian Moeller
 *
 * This program is free software; you can redistribute it and/or modify it 
 * under the terms of the GNU General Public License as published by the 
 * Free Software Foundation; either version 3 of the License, or (at your option) 
 * any later version.
 * 
 * This program is distributed in the hope that it will be useful, but 
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
 * or FITNESS FOR A PARTICULAR PURPOSE. 
 * See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program; 
 * if not, see <http://www.gnu.org/licenses/>.
 */

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.IO;

namespace FParser.Runtime
{
    public class LibraryLoader
    {
        RuntimeScope scope;
        public RuntimeScope Scope { get { return this.scope; } }

        public LibraryLoader(RuntimeScope scope)
        {
            this.scope = scope;
        }

        /// <summary>
        /// Adds a method to the method cache of the current scope
        /// </summary>
        /// <param name="_call"></param>
        public void AddMethod(ExternalLibraryCall _call)
        {
            this.scope.Methods.ExtLibs.Add(_call.Method.Name, _call);
        }

        /// <summary>
        /// Loads all methods of the library and adds them to the scope cache
        /// </summary>
        /// <param name="library"></param>
        public void AddLibrary(IBaseLibrary library)
        {
            foreach (ExternalLibraryCall _call in library.Exports)
            {
                this.AddMethod(_call);
            }
        }

        /// <summary>
        /// Loads a complete library and caches all the exported methods
        /// </summary>
        /// <param name="scope"></param>
        /// <param name="library"></param>
        public static void LoadLibrary(RuntimeScope scope, IBaseLibrary library)
        {
            LibraryLoader _tmp_Loader = new LibraryLoader(scope);
            _tmp_Loader.AddLibrary(library);
        }

        /// <summary>
        /// Loads an assembly and calls LoadLibrary for each found type mathing
        /// IBaseLibrary as BaseType
        /// </summary>
        /// <param name="scope"></param>
        /// <param name="assemblyName"></param>
        public static void LoadLibrary(RuntimeScope scope, FileInfo assemblyName)
        {
            List<IBaseLibrary> libCache = new List<IBaseLibrary>();

            if (File.Exists(assemblyName.FullName))
            {
                Assembly asmb = Assembly.LoadFile(assemblyName.FullName);
                foreach (Type type in asmb.GetTypes())
                {
                    if (type.BaseType == typeof(IBaseLibrary))
                    {
                        IBaseLibrary library = (IBaseLibrary) Activator.CreateInstance(type);
                        libCache.Add(library);
                    }
                }
            }

            foreach (IBaseLibrary lib in libCache)
            {
                LibraryLoader.LoadLibrary(scope, lib);
            }
        }

    }
}
